home *** CD-ROM | disk | FTP | other *** search
- /* new HyperCard XFCN to append or delete files
- * copyright 1988 Mark ^Zimmermann - 880901-0904
- * part of the TEX HyperCard package as an additional tool for
- * dataspace creation and navigation...
- *
- * Call this XFCN as "appendDeleteFiles (cmd)". If cmd begins with the
- * letter 'A', then a standard files dialog will offer a list of TEXT
- * files; if one is selected, then the offer will be repeated and
- * subsequent selections will be appended to the end of the first
- * one. If cmd begins with the letter 'D', then files selected from
- * the std files dialog (which shows all files now, now just TEXT files)
- * will be irreversably (probably? barring low-level magic) deleted.
- *
- * Error checking is minimal, and the usual response to an error is
- * to quit with some short message and a beep....
- */
-
-
- #include <MacTypes.h>
- #include <FileMgr.h>
- #include <StdFilePkg.h>
- #include <HyperXCmd.h>
-
- #define NULL 0
-
- /* define these to allow use of global variables in my XFCNs; a
- * Lightspeed C necessity, apparently...
- */
-
- #define SetUpA4() asm { move.l a4,-(sp) \
- move.l a0,a4 }
-
- #define RestoreA4() asm { move.l (sp)+,a4 }
-
-
- pascal void main (XCmdBlockPtr paramPtr);
- void doAppend (XCmdBlockPtr paramPtr);
- void doDelete (XCmdBlockPtr paramPtr);
- int appendNextFile (int baseFileRefNum, Str255 *nextFileName,
- int nextVolRefNum, char *bufp, long myBufSize, XCmdBlockPtr paramPtr);
- int adzGetFile (Str255 *fileNamePtr, int *volRefNumPtr, int numTypes);
- void returnErrorMsg (XCmdBlockPtr paramPtr, char *msg);
- char *strcpy (char *s1, char *s2);
- int strlen (char *s);
-
-
- pascal void main (paramPtr)
- XCmdBlockPtr paramPtr;
- {
- SetUpA4();
- switch (**(paramPtr->params[0]))
- {
- case 'A':
- doAppend (paramPtr);
- break;
- case 'D':
- doDelete (paramPtr);
- break;
- default:
- returnErrorMsg (paramPtr,
- "{Sorry, unrecognized command in appendDeleteFiles call!}");
- break;
- }
- RestoreA4();
- return;
- }
-
-
- /* function to do the work of appending files to the end of the
- * first-chosen one... determine buffer size automatically
- */
-
- void doAppend (paramPtr)
- XCmdBlockPtr paramPtr;
- {
- Str255 basefileName, nextFileName;
- int baseVolRefNum, baseFileRefNum, nextVolRefNum, nextFileRefNum;
- long myBufSize, grow;
- char *bufp;
-
- if (adzGetFile (&basefileName, &baseVolRefNum,1))
- {
- if (FSOpen (basefileName, baseVolRefNum, &baseFileRefNum) != noErr)
- {
- returnErrorMsg (paramPtr,
- "{Sorry, error while trying to open the base file!}");
- return;
- }
-
- /* see how much memory we can get for our buffer here */
- MaxApplZone();
- myBufSize = MaxMem (&grow) - 32768; /* keep 32kB in reserve */
- if ((bufp = NewPtr (myBufSize)) == NULL)
- {
- returnErrorMsg (paramPtr,
- "{Sorry, memory manager error while getting buffer space!}");
- return;
- }
-
- while (adzGetFile (&nextFileName, &nextVolRefNum, 1) &&
- appendNextFile (baseFileRefNum, &nextFileName, nextVolRefNum,
- bufp, myBufSize, paramPtr))
- ;
-
- DisposPtr (bufp);
- FSClose (baseFileRefNum);
- }
-
- return;
- }
-
-
- /* function to do the work of deleting files as they are chosen ... no
- * particular error checking, just try to do it until 'Cancel' ... beep
- * and return a polite message if unable to comply for some reason....
- */
-
- void doDelete (paramPtr)
- XCmdBlockPtr paramPtr;
- {
- Str255 fileName;
- int volRefNum;
-
- while (adzGetFile (&fileName, &volRefNum, -1))
- if (FSDelete (fileName, volRefNum) != noErr)
- {
- returnErrorMsg (paramPtr,
- "{Sorry, file system error while trying to delete a file!}");
- break;
- }
-
- return;
- }
-
-
- /* routine to append the contents of nextFile X to baseFile ... does some
- * limited error checking and tries to get a polite msg back to user if
- * there is a problem ... returns 1 if all is well, 0 on error....
- */
-
- int appendNextFile (baseFileRefNum, nextFileName, nextVolRefNum,
- bufp, myBufSize, paramPtr)
- int baseFileRefNum, nextVolRefNum;
- Str255 *nextFileName;
- char *bufp;
- long myBufSize;
- XCmdBlockPtr paramPtr;
- {
- int nextFileRefNum, errNum;
- long count;
-
- errNum = FSOpen (nextFileName, nextVolRefNum, &nextFileRefNum);
- if (errNum != noErr && errNum != opWrErr) /* ok if read-only here */
- {
- returnErrorMsg (paramPtr,
- "{Sorry, error while attempting to open file to be appended!}");
- return (0);
- }
-
- if (SetFPos (nextFileRefNum, fsFromStart, 0L) != noErr)
- {
- returnErrorMsg (paramPtr,
- "{Sorry, error setting pointer in file to be appended!}");
- FSClose (nextFileRefNum);
- return (0);
- }
- if (SetFPos (baseFileRefNum, fsFromLEOF, 0L) != noErr)
- {
- returnErrorMsg (paramPtr,
- "{Sorry, error setting pointer to end of base file!}");
- FSClose (nextFileRefNum);
- return (0);
- }
- for (;;)
- {
- count = myBufSize;
- errNum = FSRead (nextFileRefNum, &count, bufp);
- if (errNum != noErr && errNum != eofErr)
- {
- returnErrorMsg (paramPtr,
- "{Sorry, error while reading from file to be appended!}");
- FSClose (nextFileRefNum);
- return (0);
- }
- if (count == 0)
- break;
- if (FSWrite (baseFileRefNum, &count, bufp) != noErr)
- {
- returnErrorMsg (paramPtr,
- "{Sorry, error while writing to base file!}");
- FSClose (nextFileRefNum);
- return (0);
- }
- }
- FSClose (nextFileRefNum);
- return (1); /* success, at last! */
- }
-
-
- /* this routine gets the name of the file to be appended or deleted ...
- * pass it numTypes = 1 for restricting the Std Files Dialog view
- * to type 'TEXT' only, or pass numTypes = -1 to show all files.
- * The function returns 1 if a file was selected (and copies the file
- * name into the place pointed to by fileNamePtr and the volume number
- * into the place pointed to by volRefNumPtr), and returns 0 if the
- * user chooses 'Cancel'....
- */
-
- int adzGetFile (fileNamePtr, volRefNumPtr, numTypes)
- Str255 *fileNamePtr;
- int *volRefNumPtr;
- int numTypes;
- {
- SFTypeList myFileTypes;
- Point SFGwhere;
- SFReply myReply;
- register int i;
-
- SFGwhere.v = 90;
- SFGwhere.h = 82;
- myFileTypes[0] = 'TEXT';
-
- SFGetFile (SFGwhere, "\p", 0L, numTypes, myFileTypes, 0L, &myReply);
-
- if (myReply.good)
- {
- for (i = *myReply.fName; i >= 0; --i)
- (*fileNamePtr)[i] = myReply.fName[i];
- *volRefNumPtr = myReply.vRefNum;
- return (1);
- }
- else
- return (0);
- }
-
-
- /* function to set the return value of the XFCN to a chosen error msg;
- * if there isn't enough free memory to give us a Handle to the msg,
- * beep a bunch and then return!
- */
-
- void returnErrorMsg (paramPtr, msg)
- XCmdBlockPtr paramPtr;
- char *msg;
- {
- Handle answer;
- int msgLength;
-
- SysBeep (10);
- msgLength = strlen (msg);
- if ((answer = NewHandle (1 + msgLength)) == NULL)
- {
- SysBeep (10);
- SysBeep (10);
- SysBeep (10);
- SysBeep (10);
- SysBeep (10);
- return;
- }
-
- strcpy (*answer, msg);
- paramPtr->returnValue = answer;
- return;
- }
-
-
- /* function to determine the length of a string ... standard thing,
- * adapted from the LSC library, and K&R p.98 ....
- */
-
- int strlen (s)
- register char *s;
- {
- char *s0 = s;
-
- while (*s++)
- ;
- return (s - s0 - 1);
- }
-
-
- /* function to copy a string from one place to another, in a rather
- * obvious fashion ... adapted from the LSC library, and K&R p.101 ....
- */
-
- char *strcpy (s1, s2)
- register char *s1, *s2;
- {
- char *s = s1;
-
- while (*s1++ = *s2++)
- ;
- return (s);
- }
-